/*
 * Item.java
 * Team qq 2011
 */
package com.google.code.timetrail.backend;

import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;

/**
 * An interface that provides all that needs to be known about items
 * for things like inventory adding and removing 
 * @author Steven
 * @version 1.0
 */
public abstract class Item {
	
	/** The logger object for Item*/
	public static final Logger LOGGER = Logger.getLogger(Item.class);
	
	/** The minimum amount of any item*/
	public static final int MIN_AMOUNT = 0;

	/** The current amount of that item in an instance*/
	protected int currentAmount;
	
	/**
	 *  Instantiate currentAmount
	 */
	public Item(){
		currentAmount = 0;
		PropertyConfigurator.configure("time.properties");
	}

	/**
	 * returns the weight of one unit of that item
	 * @return the item's weight
	 */
	public abstract int getWeight();
	
	/**
	 * returns the item's value
	 * @return the value in money for one unit of that item
	 */
	public abstract int getValue();
	
	/**
	 * provides a maximum amount of that item that can be in the inventory
	 * 
	 * @return the maximum amount of items 
	 */
	public abstract int getMaxAmount();
	
	/**
	 * returns the current amount of that item in a given instance
	 * @return the amount of items currently there
	 */
	public int getCurrentAmount(){
		return currentAmount;
	}

	/**
	 * set the current amount of the item, from min-max
	 * @param amount the amount to set the item to 
	 */
	public void setCurrentAmount(int amount){
		if(amount > getMaxAmount() || amount < MIN_AMOUNT){
			LOGGER.warn("Setting " + amount + " for " + this + " failed.");
			return;
		}
		else{
			this.currentAmount = amount;
			LOGGER.debug(this + " has had its amount changed to " 
						+ amount);
		}
	}
		
	/**
	 * adds to the current amount of items in the object
	 * @param amount the amount to add in
	 * @return true for success and false for failure
	 */
	public boolean canAddCurrentAmount(int amount){
		if((amount + getCurrentAmount()) > getMaxAmount() 
				|| (amount + getCurrentAmount()) < MIN_AMOUNT){
			LOGGER.info(this + " could not add " + amount 
					     + " to its current amount");
			return false;
		}
		else{
			LOGGER.info(this + " will add " + amount 
					+ "to its current amount");
			currentAmount += amount;
			return true;
		}
	}
	
	/**
	 * same thing as addCurrentAmount, 
	 * but with the option of a dry run where nothing is changed
	 * @param amount the number of items to add
	 * @param dryRunFlag to do a dry run or not
	 * @return true for success and false for failure
	 */
	public boolean canAddCurrentAmount(int amount, boolean dryRunFlag){
		if(dryRunFlag){
			if(!((amount + getCurrentAmount()) > getMaxAmount() 
                    || (amount + getCurrentAmount()) < MIN_AMOUNT)){
				LOGGER.info(amount + " could be added to " + this);
			}
			else{
				LOGGER.info(amount + " could not be added to " + this);
			}
			return !((amount + getCurrentAmount()) > getMaxAmount() 
                    || (amount + getCurrentAmount()) < MIN_AMOUNT);
		}
		else{
			LOGGER.warn("Cleared for adding an item");
			return canAddCurrentAmount(amount);
		}
	}

	/**
	 * acts as a wrapper to negative amounts in addCurrentAmount
	 * @param amount the amount to subtract
	 * @return true for success and false for failure
	 */
	public boolean canRemoveCurrentAmount(int amount){
		if(amount < 0){
			return false;
		}
		else{
			return canAddCurrentAmount((-1 * amount));
		}
	}

	/**
	 * same thing as removeCurrentAmount with the added option 
	 * of a dry run flag where nothing is changed
	 * @param amount the amount to subtract
	 * @param dryRunFlag true to dry run and false for a regular run
	 * @return true for success and false for failure
	 */
	public boolean canRemoveCurrentAmount(int amount, boolean dryRunFlag){
		if(amount < 0){
			return false;
		}
		else{
			return canAddCurrentAmount(amount, dryRunFlag);
		}
	}

	/**
	 * returns the name of that item
	 * @return the name of the item
	 */
	public abstract String getItemName();
	
	/**
	 * The string representation for an Item
	 * @return the item's name
	 */
	@Override
	public String toString(){
		return getItemName();
	}
}
